package com.glink.manage.service.Impl;

import com.glink.common.contants.BaseConstants;
import com.glink.common.exception.GeneralSimpleException;
import com.glink.manage.common.Constants;
import com.glink.manage.common.RedisUtil;
import com.glink.manage.common.sm.Sm2Encryption;
import com.glink.manage.common.sm.Sm3Encryption;
import com.glink.manage.service.PasswordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : qiushaoshan
 * @create 2024/6/18 10:50
 */
@Service
@Slf4j
public class PasswordServiceImpl implements PasswordService {
    
    @Value("${user.default_password: null}")
    private String defaultPassword;
    
    @Autowired
    private RedisUtil redisUtil;

    private static Sm2Encryption sm2Encryption;
    private static Sm3Encryption sm3Encryption;
    
    static {
        try {
            sm2Encryption = Sm2Encryption.createInstance();
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("初始国密加密算法失败sm2" + e);
            System.exit(0);
        }
        
        try {
            sm3Encryption = Sm3Encryption.createInstance();
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("初始国密加密算法失败sm3" + e);
            System.exit(0);
        }
        
    }
    
    @Override
    public String getDefaultPassword(){
        if(defaultPassword == null || StringUtils.equals(defaultPassword, "null")){
            return Constants.DEFAULT_PASSWORD;            
        }else {
            return defaultPassword;
            
        }
    }
    /**
     * 对密码产生国密
     * @param plainPassword 密码明文
     * @param salt 盐
     * @return 密文密码
     */
    @Override
    public String generateBySm3(String plainPassword, String salt) {
        String sm3Data = sm3Encryption.hash1(salt + plainPassword + BaseConstants.MD5_SALT);
        log.info("plainPassword-{}  sm3str-{}", plainPassword, sm3Data);
        return sm3Data;
    }

    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public String onlyDecryptAndRemoveKey(String privateKey, String cipher) throws GeneralSimpleException {
        long start = System.currentTimeMillis();
        if (StringUtils.length(cipher) <= 0) {
            throw new GeneralSimpleException("400011");
        }
        cipher = StringUtils.replace(cipher, " ", "+");
        String[] plain = onlyDecrypt(privateKey, cipher);
        log.info("sm2 onlyDecryptAndRemoveKey 解密并耗时 {}", System.currentTimeMillis() - start);
        return plain[1];
    }

    public String[] onlyDecrypt(String pubKey, String cipher) throws GeneralSimpleException {
        if (StringUtils.length(cipher) <= 0) {
            throw new GeneralSimpleException("400011");
        }
        return extractPassword(pubKey, cipher);
    }

    private String[] extractPassword(String pubKey, String cipher) throws GeneralSimpleException {
        String[] ret = new String[2];
        String plain = "";
        try {
            plain = decrypt(pubKey, cipher);
            if (StringUtils.length(plain) <= 4) {
                throw new GeneralSimpleException("400011");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new GeneralSimpleException("400012");
        }

        String rand = StringUtils.substring(plain, 0, 4);
        //不存在随机数
        if (!existKey(rand)) {
            log.error("随机数{}不存在,不能再次登录", rand);
            throw new GeneralSimpleException("400013");
        }
        delRandomKey(rand);
        ret[0] = rand;
        ret[1] = StringUtils.substring(plain, 4);
        return ret;
    }

    public boolean existKey(String random) {
        String key = StringUtils.join(Constants.RANDOM_KEY_PREFIX, random);
        return redisUtil.hasKey(key);
    }

    public void delRandomKey(String random) {
        String key = StringUtils.join(Constants.RANDOM_KEY_PREFIX, random);
        redisUtil.del(key);
    }
    
    public String decrypt(String privateKey, String str) throws BadPaddingException, IllegalBlockSizeException {
        String plainText = sm2Encryption.decrypt(privateKey, str);
        log.info("解密后明文为{}", plainText);
        return plainText;
    }

    @Override
    public String encrypt(String publicKey, String str) throws Exception {
        String cipherText = sm2Encryption.encrypt(publicKey, str);
        log.info("sm2加密后的密文:{}", cipherText);
        return cipherText;
    }

    @Override
    public String sm3(String plainText) {
        return sm3Encryption.hash1(plainText);
    }

}
